﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Runtime.InteropServices;
using SystemWindowsForms = System.Windows.Forms;
using WindowsInput.Native;
using System.Collections.ObjectModel;

namespace UniPie
{
	/// <summary>
	/// Helper class for storing utility functions.
	/// </summary>
	internal static class Helpers
	{
		[StructLayout(LayoutKind.Sequential)]
		public struct POINTAPI
		{
			public int X;
			public int Y;

			public POINTAPI(int x, int y)
			{
				this.X = x;
				this.Y = y;
			}
		}

		/// <summary>
		/// Gets the virtual keycode of a key.
		/// </summary>
		public static WindowsInput.Native.VirtualKeyCode GetVirtualKeyCode(SystemWindowsForms.Keys key)
		{
			return (WindowsInput.Native.VirtualKeyCode)key;
		}

		/// <summary>
		/// Gets the virtual keycode of a mouse button.
		/// </summary>
		public static WindowsInput.Native.VirtualKeyCode GetVirtualKeyCode(SystemWindowsForms.MouseButtons mousebutton)
		{
			switch (mousebutton.ToString())
			{
				case "Left":
					return VirtualKeyCode.LBUTTON;

				case "Right":
					return VirtualKeyCode.RBUTTON;

				case "Middle":
					return VirtualKeyCode.MBUTTON;

				default:
					return VirtualKeyCode.NONAME;
			}
		}

		/// <summary>
		/// Sorts a collection of virtual keycodes so modifiers are listed first.
		/// </summary>
		public static ObservableCollection<VirtualKeyCode> SortVirtualKeyCodes(ObservableCollection<VirtualKeyCode> vkcc)
		{
			VirtualKeyCode[] vkca = vkcc.ToArray();
			ObservableCollection<VirtualKeyCode> ReturnValue = new ObservableCollection<VirtualKeyCode>();

			Array.Sort(vkca);

			foreach (VirtualKeyCode vkc in vkca)
			{
				ReturnValue.Add(vkc);
			}

			if (ReturnValue.Contains(VirtualKeyCode.LCONTROL))
			{
				ReturnValue.Remove(VirtualKeyCode.LCONTROL);
				ReturnValue.Insert(0, VirtualKeyCode.LCONTROL);
			}
			if (ReturnValue.Contains(VirtualKeyCode.RCONTROL))
			{
				ReturnValue.Remove(VirtualKeyCode.RCONTROL);
				ReturnValue.Insert(0, VirtualKeyCode.RCONTROL);
			}

			if (ReturnValue.Contains(VirtualKeyCode.LMENU))
			{
				ReturnValue.Remove(VirtualKeyCode.LMENU);
				ReturnValue.Insert(0, VirtualKeyCode.LMENU);
			}
			if (ReturnValue.Contains(VirtualKeyCode.RMENU))
			{
				ReturnValue.Remove(VirtualKeyCode.RMENU);
				ReturnValue.Insert(0, VirtualKeyCode.RMENU);
			}

			if (ReturnValue.Contains(VirtualKeyCode.LSHIFT))
			{
				ReturnValue.Remove(VirtualKeyCode.LSHIFT);
				ReturnValue.Insert(0, VirtualKeyCode.LSHIFT);
			}
			if (ReturnValue.Contains(VirtualKeyCode.RSHIFT))
			{
				ReturnValue.Remove(VirtualKeyCode.RSHIFT);
				ReturnValue.Insert(0, VirtualKeyCode.RSHIFT);
			}

			if (ReturnValue.Contains(VirtualKeyCode.LWIN))
			{
				ReturnValue.Remove(VirtualKeyCode.LWIN);
				ReturnValue.Insert(0, VirtualKeyCode.LWIN);
			}
			if (ReturnValue.Contains(VirtualKeyCode.RWIN))
			{
				ReturnValue.Remove(VirtualKeyCode.RWIN);
				ReturnValue.Insert(0, VirtualKeyCode.RWIN);
			}

			return ReturnValue;
		}

		/// <summary>
		/// Helper method for generating a "pack://" URI for a given relative file based on the
		/// assembly that this class is in.
		/// </summary>
		public static Uri MakePackUri(string relativeFile)
		{
			string uriString = "pack://application:,,,/" + AssemblyShortName + ";component/" + relativeFile;
			return new Uri(uriString);
		}

		private static string AssemblyShortName
		{
			get
			{
				if (_assemblyShortName == null)
				{
					Assembly a = typeof(Helpers).Assembly;

					// Pull out the short name.
					_assemblyShortName = a.ToString().Split(',')[0];
				}

				return _assemblyShortName;
			}
		}

		private static string _assemblyShortName;
	}
}
